﻿using Castle.DynamicProxy;
using FastReflectionLib;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AOP
{
    public class ProxyGeneratorOptimize : ProxyGenerator
    {
        public ProxyGeneratorOptimize()
            : base()
        {
        }

        public ProxyGeneratorOptimize(IProxyBuilder builder)
            : base(builder)
        {
        }

        public override object CreateInterfaceProxyWithTarget(Type interfaceToProxy, Type[] additionalInterfacesToProxy,
                                                             object target,
                                                             ProxyGenerationOptions options,
                                                             params IInterceptor[] interceptors)
        {
            if (interfaceToProxy == null)
            {
                throw new ArgumentNullException("interfaceToProxy");
            }
            if (target == null)
            {
                throw new ArgumentNullException("target");
            }
            if (interceptors == null)
            {
                throw new ArgumentNullException("interceptors");
            }

            if (!interfaceToProxy.IsInterface)
            {
                throw new ArgumentException("Specified type is not an interface", "interfaceToProxy");
            }

            var targetType = target.GetType();
            if (!interfaceToProxy.IsAssignableFrom(targetType))
            {
                throw new ArgumentException("Target does not implement interface " + interfaceToProxy.FullName, "target");
            }

            CheckNotGenericTypeDefinition(interfaceToProxy, "interfaceToProxy");
            CheckNotGenericTypeDefinitions(additionalInterfacesToProxy, "additionalInterfacesToProxy");

            var generatedType = CreateInterfaceProxyTypeWithTarget(interfaceToProxy, additionalInterfacesToProxy, targetType,
                                                                   options);
            var arguments = GetConstructorArguments(target, interceptors, options);
            var paramTypes = arguments.Select(arg => arg.GetType()).ToArray();

            var ctorInvoker = FastReflectionCaches.ConstructorInvokerCache.Get(generatedType.GetConstructor(paramTypes));
            return ctorInvoker.Invoke(arguments.ToArray());
            //return Activator.CreateInstance(generatedType, arguments.ToArray());
        }
    } // end ProxyGeneratorOptimize
} // end namespace Auto.Dealer.AOP
